package com.coderly.onlinegallerysharingplatform.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.secure.SaSecureUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.coderly.onlinegallerysharingplatform.common.constant.RedisKeyConstants;
import com.coderly.onlinegallerysharingplatform.common.convention.errorcode.ErrorCode;
import com.coderly.onlinegallerysharingplatform.common.convention.exception.BizException;
import com.coderly.onlinegallerysharingplatform.common.response.Response;
import com.coderly.onlinegallerysharingplatform.model.dao.entity.UserDO;
import com.coderly.onlinegallerysharingplatform.model.dto.req.user.*;
import com.coderly.onlinegallerysharingplatform.model.dto.resp.user.GetUserDateCountInfoRespDTO;
import com.coderly.onlinegallerysharingplatform.model.dto.resp.user.UserRespDTO;
import com.coderly.onlinegallerysharingplatform.model.dto.resp.user.UserLoginRespDTO;
import com.coderly.onlinegallerysharingplatform.service.UserService;
import com.coderly.onlinegallerysharingplatform.toolkit.ExceptionTrowUtils;
import com.coderly.onlinegallerysharingplatform.toolkit.UserUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;

@RestController
@RequiredArgsConstructor
@Validated
public class UserController {

    private final UserService userService;


    /**
     * 登录
     *
     * @param requestParam
     * @return
     */
    @PostMapping("/user/login")
    public Response<String> loginAndRegister(@RequestBody @Valid UserLoginAndRegisterReqDTO requestParam) {
        String tokenValue = userService.loginAndRegister(requestParam);
        return Response.success(tokenValue);
    }


    /**
     * 发送验证码
     *
     * @param sendVerificationCodeReqDTO
     * @return
     */
    @PostMapping("/user/verification/code/send")
    public Response<String> send(@Validated @RequestBody SendVerificationCodeReqDTO sendVerificationCodeReqDTO) {
        userService.send(sendVerificationCodeReqDTO);
        return Response.success("ok");
    }

    /**
     * 获取当前登录用户
     *
     * @return
     */
    @GetMapping("/user/get/login")
    public Response<UserLoginRespDTO> getLoginUser() {
        UserDO loginUser = userService.getLoginUser();
        UserLoginRespDTO userLoginRespDTO = new UserLoginRespDTO();
        BeanUtil.copyProperties(loginUser, userLoginRespDTO);
        return Response.success(userLoginRespDTO);
    }

    /**
     * 退出登录
     *
     * @param
     * @return
     */
    @PostMapping("/user/logout")
    public Response<Boolean> logout() {
        Boolean result = userService.logout();
        return Response.success(result);
    }

    /**
     * 根据 id 获取脱敏后用户信息
     */
    @GetMapping("/user/get/vo")
    public Response<UserRespDTO> getUserVOById(long id) {
        Response<UserDO> response = getUserById(id);
        UserDO user = response.getData();
        return Response.success(userService.getUser(user));
    }

    /**
     * 创建用户
     *
     * @param addUserReqDTO
     * @return
     */
    @PostMapping("/admin/user/add")
    public Response<Long> addUser(@RequestBody AddUserReqDTO addUserReqDTO) {
        ExceptionTrowUtils.throwIf(addUserReqDTO == null, ErrorCode.PARAMS_ERROR);
        UserDO userDO = new UserDO();
        BeanUtil.copyProperties(addUserReqDTO, userDO);
        // TODO 设置参数
        boolean save = userService.save(userDO);
        if (!save) {
            throw new BizException(ErrorCode.OPERATION_ERROR);
        }
        return Response.success(userDO.getId());
    }


    /**
     * 根据 id 获取用户（仅管理员）
     */
    @GetMapping("/admin/user/get")
    public Response<UserDO> getUserById(long id) {
        ExceptionTrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        UserDO user = userService.getById(id);
        ExceptionTrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR);
        return Response.success(user);
    }

    /**
     * 删除用户
     */
    @PostMapping("/admin/user/delete")
    public Response<Boolean> deleteUser(@RequestBody DeleteUserReqDTO deleteRequest) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BizException(ErrorCode.PARAMS_ERROR);
        }
        boolean b = userService.removeById(deleteRequest.getId());
        return Response.success(b);
    }

    /**
     * 更新用户
     */
    @PostMapping("/admin/user/update")
    public Response<Boolean> updateUser(@RequestBody UpdateUserReqDTO updateUserReqDTO) {
        if (updateUserReqDTO == null || updateUserReqDTO.getId() == null) {
            throw new BizException(ErrorCode.PARAMS_ERROR);
        }
        UserDO user = new UserDO();
        BeanUtils.copyProperties(updateUserReqDTO, user);
        boolean result = userService.updateById(user);
        ExceptionTrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return Response.success(true);
    }

    /**
     * 分页获取用户封装列表（仅管理员）
     *
     * @param getUserReqDTO 查询请求参数
     */
    @PostMapping("/admin/user/list/page/vo")
    public Response<Page<UserRespDTO>> listUserVOByPage(@RequestBody GetUserReqDTO getUserReqDTO) {
        ExceptionTrowUtils.throwIf(getUserReqDTO == null, ErrorCode.PARAMS_ERROR);
        long current = getUserReqDTO.getCurrent();
        long pageSize = getUserReqDTO.getPageSize();
        Page<UserDO> userPage = userService.page(new Page<>(current, pageSize),
                userService.getQueryWrapper(getUserReqDTO));
        Page<UserRespDTO> userVOPage = new Page<>(current, pageSize, userPage.getTotal());
        List<UserRespDTO> userVOList = userService.getUserList(userPage.getRecords());
        userVOPage.setRecords(userVOList);
        return Response.success(userVOPage);
    }

    /**
     * 获取指定用户个人主页数据详情
     *
     * @param userId
     * @return
     */
    @GetMapping("/user/getDataInfo/count")
    public Response<GetUserDateCountInfoRespDTO> getUserDateCountInfo(long userId) {
        return userService.getUserDateCountInfo(userId);
    }

    /**
     * 统计图片发布热点图
     *
     * @return
     */
    @GetMapping("/user/heatmap")
    @SaIgnore
    public Response<Map<LocalDate, Long>> getUserPictureUploadHeatMap() {
        return Response.success(userService.getUserPictureUploadHeatMap());
    }

    /**
     * 更新用户
     */
    @PostMapping("/user/update")
    public Response<Boolean> updateUserProfile(@RequestBody UpdateUserReqDTO updateUserReqDTO) {
        if (updateUserReqDTO == null
                || updateUserReqDTO.getId() == null
                || !updateUserReqDTO.getId().equals(UserUtil.getLoginUserId())) {
            throw new BizException(ErrorCode.PARAMS_ERROR);
        }
        UserDO user = new UserDO();
        BeanUtils.copyProperties(updateUserReqDTO, user);
        boolean result = userService.updateById(user);
        ExceptionTrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return Response.success(true);
    }

    /**
     * 修改密码
     */
    @PostMapping("/user/change_password")
    public Response<Boolean> changePassword(@RequestBody ChangePasswordReqDTO changePasswordReqDTO) {
        if (changePasswordReqDTO == null
                || !changePasswordReqDTO.getPassword().equals(changePasswordReqDTO.getCheckedPassword())) {
            throw new BizException(ErrorCode.PARAMS_ERROR);
        }
        // 获取登录用户
        Long loginUserId = UserUtil.getLoginUserId();
        // 获取新密码
        String password = changePasswordReqDTO.getPassword();
        // 加密密码
        String encryptPassword = BCrypt.hashpw(password, BCrypt.gensalt(10));
        // 更新用户密码
        boolean update = userService.lambdaUpdate()
                .eq(UserDO::getId, loginUserId)
                .set(UserDO::getPassword, encryptPassword)
                .update();
        return Response.success(update);
    }

    /**
     * 修改手机号
     */
    @PostMapping("/user/change_phone")
    public Response<Boolean> changePhone(@RequestBody ChangePhoneReqDTO changePhoneReqDTO) {
        // 校验参数
        ExceptionTrowUtils.throwIf(changePhoneReqDTO == null, ErrorCode.PARAMS_ERROR);
        return Response.success(userService.changePhone(changePhoneReqDTO));
    }

    /**
     * 删除账号
     */
    @PostMapping("/user/delete_account")
    public Response<Boolean> deleteAccount() {
        // 获取当前登录用户
        Long loginUserId = UserUtil.getLoginUserId();
        // 测试环境下逻辑删除用户
        boolean update = userService.lambdaUpdate()
                .eq(UserDO::getId, loginUserId)
                .set(UserDO::getIsDeleted, 1)
                .update();
        return Response.success(update);
    }

}
